package com.naiterui.ehp.bs.b2c.pharmacy.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import com.google.common.base.Preconditions;
import com.naiterui.common.redis.RedisUtil;
import com.naiterui.ehp.bp.constants.CommonConstant;
import com.naiterui.ehp.bp.utils.thread.ThreadPoolUtil;
import com.naiterui.ehp.bs.b2c.inventory.service.IStockService;
import com.naiterui.ehp.bs.b2c.pharmacy.bo.WarehouseBO;
import com.naiterui.ehp.bs.b2c.pharmacy.entity.Warehouse;
import com.naiterui.ehp.bs.b2c.pharmacy.exception.PharmacyBusinessException;
import com.naiterui.ehp.bs.b2c.pharmacy.exception.PharmacyExceptionCodes;
import com.naiterui.ehp.bs.b2c.pharmacy.repository.IWarehouseRepository;
import com.naiterui.ehp.bs.b2c.pharmacy.service.IWarehouseService;

@Lazy
@Service
public class WarehouseServiceImpl implements IWarehouseService {

    @Autowired
    private IStockService stockService;
    @Autowired
    private IWarehouseRepository warehouseRepository;
    private static final String SERIAL_CODE_REDIS_KEY = CommonConstant.REDIS_PRE_B2C + "WAREHOUSE_CODE_SERIAL_NUMBER";

    @Override
    public Long saveOrUpdate(WarehouseBO warehouseBo, String operator) throws PharmacyBusinessException {
        Long id = warehouseBo.getId();
        Warehouse warehouse = Optional.ofNullable(id)
                                      .map(aLong -> this.warehouseRepository.get(aLong))
                                      .orElseGet(() -> {
                                          Warehouse newWarehouse = new Warehouse();
                                          newWarehouse.setCreatedAt(new Date());
                                          newWarehouse.setCreatedBy(operator);
                                          return newWarehouse;
                                      });
        if (id == null && this.warehouseRepository.existsByName(warehouseBo.getName())) {
            throw new PharmacyBusinessException(PharmacyExceptionCodes.FAILED, "商家名称不能重复");
        }
        if (id != null && this.warehouseRepository.existsByIdNotAndName(id, warehouseBo.getName())) {
            throw new PharmacyBusinessException(PharmacyExceptionCodes.FAILED, "商家名称不能重复");
        }
        BeanUtils.copyProperties(warehouseBo, warehouse);
        warehouse.setChangedBy(operator);
        warehouse.setChangedAt(new Date());
        if (id == null) {
            long serialNumber = RedisUtil.keyOps().incr(SERIAL_CODE_REDIS_KEY);
            warehouse.setCode(10000 + serialNumber + "");
            warehouse.setNumber(0);
            warehouse.setStatus(Warehouse.STATUS_NORMAL);
            this.warehouseRepository.save(warehouse);
        } else {
            this.warehouseRepository.update(warehouse);
        }

        if (RedisUtil.keyOps().existsKey(CommonConstant.SUPERVISE_SYNCHRONIZE_KEY)) {
            // 异步调用
            ThreadPoolUtil.execute(() -> {
                // 同步药店信息至监管平台
                RedisUtil.listOps().lpush(CommonConstant.SUPERVISE_PUSH_WAREHOUSE_LIST_KEY, warehouse.getId() + "");
            });
        }
        return warehouse.getId();
    }

    @Override
    public void updateStatus(Long id, Integer status, String operator) {
        Warehouse warehouse = this.warehouseRepository.get(id);
        Preconditions.checkNotNull(warehouse, String.format("当前仓库不能为null %d", id));
        warehouse.setStatus(status);
        warehouse.setChangedAt(new Date());
        warehouse.setChangedBy(operator);
        this.warehouseRepository.update(warehouse);
        this.stockService.updateStatus(id, status, operator);

        if (RedisUtil.keyOps().existsKey(CommonConstant.SUPERVISE_SYNCHRONIZE_KEY)) {
            // 异步调用
            ThreadPoolUtil.execute(() -> {
                // 同步药店信息至监管平台
                RedisUtil.listOps().lpush(CommonConstant.SUPERVISE_PUSH_WAREHOUSE_LIST_KEY, warehouse.getId() + "");
            });
        }
    }

    @Override
    public List<Long> getAllWarehouseIds() {
        List<Warehouse> warehouses = warehouseRepository.findAllByStatus(Warehouse.STATUS_NORMAL);
        List<Long> warehouseIds = warehouses.stream().map(Warehouse::getId).collect(Collectors.toList());
        return warehouseIds.stream().distinct().collect(Collectors.toList());
    }

    @Override
    public void checkStatusNormal(Long id) throws PharmacyBusinessException {
        Warehouse warehouse = this.warehouseRepository.get(id);
        if (warehouse.getStatus() == Warehouse.STATUS_DISABLE) {
            throw new PharmacyBusinessException(PharmacyExceptionCodes.USER_NOT_NOMAL);
        }
    }

}
